/*
 * InputArray.cpp
 *
 *  Created on: Mar 28, 2011
 *      Author: skyang
 */
#include "InputArray.h"

#include <fstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

using namespace std;
void InputArray :: PrintElements(bool printWholeArray){

/*	int index;
	int ArrayLength;
	double CurrentArray [500];
	double PushElement;
	double PopElement;
	double ArrayMax;
	double ArrayMin;*/

	cout << "Current Index of Circular array is: " << index << endl;
	cout << "Array Length is: " << ArrayLength << endl;
	cout << "Minimum Element is: " << ArrayMin << endl;
	cout << "Maximum Element is: " << ArrayMax<< endl;
	cout << "Push Element is " << PushElement << endl;
	cout << "Pop Element is" << PopElement << endl;
	cout << "Number of Different Elements in Data (tableLength): " << tableLength << endl;
	cout << "Printing Table:" << endl;

	for (int i = 0; i < tableLength; i++){
		cout << "Table Element : " << i << "   Value = " << TablePointer[i].ValueofElement << "   Repetition = " << TablePointer[i].NumberofElements << endl;
	}

	if (printWholeArray){
		cout << "Printing Entire Array" << endl;
		for (int i = 0; i<ArrayLength; i++){
			cout << "Array Element " << i << " is : " << CurrentArrayPtr[i] << endl;
		}
	}
	return;
}

bool InputArray :: InitiateArray(fstream & myfile){
	index = 0;
	double d;
	double max = 0;
	double min = 1.79769e+308;
	for (int i = 0; i < ArrayLength; i++){
		TablePointer[i].NumberofElements = 0;
		TablePointer[i].ValueofElement = -1;
	}

	if(!myfile) //Always test the file open.
	    {
	          cout<<"Error opening output file"<<endl;
	          //system("pause");
	          return false;
	    }
	while(index<ArrayLength){

		if (myfile.eof()){
			cout << "Unexpected end of file"<< endl;
			return false;
		}

		myfile >> d;

		CurrentArrayPtr[index++] = d;
		// Fill up the table.
		int TableIndex = -1;
		int index2 = 0;
		// Look for the next empty table,
		for (int i = 0; i < ArrayLength; i++){
			if(TablePointer[i].ValueofElement == d)
				TableIndex = i;
		}

		// The element did not exist in the table
		if (TableIndex == -1){
			while(TablePointer[index2].ValueofElement != -1)
				index2++;
			TablePointer[index2].ValueofElement = d;
			TablePointer[index2].NumberofElements = 1;
			tableLength ++;
		}
		// The element did exist in the table.
		else
			TablePointer[TableIndex].NumberofElements++;

		if (d > max) max = d;
		if (d < min) min = d;
	}

	///////////////////////////////////////////////////////////////////////////////
	// Sort the Table so that TablePointer[i].ValueofElement increase as i increases
	///////////////////////////////////////////////////////////////////////////////
	double tmp;
	int tmp2;
	for(int i = 0; i < tableLength-1 ;i++){
		for (int j = i + 1;j < tableLength;j++){
			if (TablePointer[i].ValueofElement > TablePointer[j].ValueofElement){
				tmp  = TablePointer[i].ValueofElement;
				TablePointer[i].ValueofElement = TablePointer[j].ValueofElement;
				TablePointer[j].ValueofElement = tmp;
				tmp2 = TablePointer[i].NumberofElements;
				TablePointer[i].NumberofElements = TablePointer[j].NumberofElements;
				TablePointer[j].NumberofElements = tmp2;
			}
		}
	}
	////////////////////////////////////////////////////////////////
	// Finished Sorting
	////////////////////////////////////////////////////////////////

	ArrayMax = max;
	ArrayMin = min;

	return true;
}



bool InputArray :: UpdateArray(fstream & myfile){

	// needSortIncreaseTableLength becomes true when there is a new element
	// needSortDecreaseTableLength becomes true when an old element is all finished.
	bool needSortIncreaseTableLength = false;
	bool needSortDecreaseTableLength = false;

	double d;
	if (!myfile){
        cout<<"Error opening output file"<<endl;
        //system("pause");
        return false;
	}

	index = index % ArrayLength;

	if (myfile.eof()){
		cout << "Reached end of data." << endl;
		return false;
	}

	myfile >> d;

	///////////////////////////////////////////////////////////////////////
	// Update the table for the push element
	///////////////////////////////////////////////////////////////////////

	int TableIndex = -1;
	int index2 = 0;
	for (int i = 0; i < ArrayLength; i++){
		if(TablePointer[i].ValueofElement == d){
			TableIndex = i;
			break;
		}
	}
	// The element did not exist in the table
	if (TableIndex == -1){
		// Find an empty place in the table
		while(TablePointer[index2].NumberofElements != 0)
			index2++;
		// Insert into the empty place.
		TablePointer[index2].ValueofElement = d;
		TablePointer[index2].NumberofElements = 1;

		// increment the table length
		tableLength++;
		// indicate that we need to sort the table.
		needSortIncreaseTableLength = true;
	}

	// The element did exist in the table.
	else
		TablePointer[TableIndex].NumberofElements++;

	// update the max and min elements, in the case that the max increased or min decreased.
	if (d > ArrayMax) ArrayMax = d;
	if (d < ArrayMax) ArrayMin = d;
	PopElement = CurrentArrayPtr[index];

	////////////////////////////////////////////////////////////////////////////////
	// Update the table for the popped element.
	////////////////////////////////////////////////////////////////////////////////
	for (int i = 0; i < ArrayLength; i++){
		if(TablePointer[i].ValueofElement == PopElement){
			TableIndex = i;
			break;
		}
	}
	/////////////////////////////////////////////////////////////////////////////////
	// This is the last element popped from this table entry
	// This table entry will now be empty
	/////////////////////////////////////////////////////////////////////////////////
	if (TablePointer[TableIndex].NumberofElements == 1){
		TablePointer[TableIndex].NumberofElements = 0;
		TablePointer[TableIndex].ValueofElement = -1;

		// One entry is removed from the table so it needs to be resorted
		needSortDecreaseTableLength = true;
		// The table length has decreased, but it cannot decrease until after sorting.
	}

	else  // Here the number of elements of that value is not 1, so we just need to decrease the number of elements.
		TablePointer[TableIndex].NumberofElements--;
	/////////////////////////////////////////////////////////////////////////
	// Finished working with the popped element
	/////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////////////////
	// Sort the table according to the two boolean variables:
	// needSortDecreaseTableLength and needSortIncreaseTableLength
	// There are 4 cases:
	// 1. both are false: No need to sort
	//
	// 2. Increase is true: This means we have increased tableLength by 1,
	// 						Do a complete sort in this case
	//
	// 3. Decrease is true: This means tableLength is same as before
	//					    But there is an entry in the table that is empty.
	//						Copy those empty entries from the back to the front
	//						Then decrease tableLength at the end
	//
	// 4. both are true: 	Step 1: move the entries from back to front,
	//								eliminating the empty spot, decrease tableLength
	//						Step 2: Sort the table again, take care of the extra entry
	//////////////////////////////////////////////////////////////////////////////////////////

	if (needSortDecreaseTableLength){
//		cout << "Table Decreased" << endl;
		int decreaseIndex = 0;
		// Find the index where the element is missing.
		while (TablePointer[decreaseIndex].NumberofElements != 0)
			decreaseIndex++;
		// Move elements to cover the missing index.
		for (int i = decreaseIndex; i < tableLength-1; i++){
				TablePointer[i].NumberofElements = TablePointer[i+1].NumberofElements;
				TablePointer[i].ValueofElement = TablePointer[i+1].ValueofElement;
		}
		// Zero out the last element.
		TablePointer[tableLength-1].NumberofElements = 0;
		TablePointer[tableLength-1].ValueofElement = -1;

		// decrease the tableLength
		tableLength--;

		// Update the max and min values.
		ArrayMax = TablePointer[tableLength-1].ValueofElement;
		ArrayMin= TablePointer[0].ValueofElement;
//		this->PrintElements(false);
	}

	if (needSortIncreaseTableLength){
		double tmp;
		int tmp2;
		for(int i = 0; i < tableLength-1 ;i++){
			for (int j = i + 1;j < tableLength;j++){
				if (TablePointer[i].ValueofElement > TablePointer[j].ValueofElement){
					tmp  = TablePointer[i].ValueofElement;
					TablePointer[i].ValueofElement = TablePointer[j].ValueofElement;
					TablePointer[j].ValueofElement = tmp;
					tmp2 = TablePointer[i].NumberofElements;
					TablePointer[i].NumberofElements = TablePointer[j].NumberofElements;
					TablePointer[j].NumberofElements = tmp2;
				}
			}
		}
	}
	///////////////////////////////////////////////////////////////////////////////
	// Finished Sorting of Table
	///////////////////////////////////////////////////////////////////////////////

	CurrentArrayPtr[index++] = d;
	PushElement = d;
	return true;
}

double * InputArray :: getArray(){
	double * p;
	p = CurrentArrayPtr;
	return p;
}

double InputArray :: getPopElement(){
	return PopElement;
}

double InputArray :: getPushElement(){
	return PushElement;
}

int InputArray :: getArrayLength(){
	return ArrayLength;
}

